package org.budo.jdbc.dao.ddl.auto.dialect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;

/**
 * @author limingwei
 */
public class MySqlDialect implements Dialect {
    @Override
    public String addColumn(Field field) {
        Table table = field.getDeclaringClass().getAnnotation(Table.class);
        String tableName = table.name();
        return "ALTER TABLE " + tableName + " ADD " + this.columnName(field) + " " + this.columnType(field);
    }

    public String createTable(Class<?> type) {
        Table table = type.getAnnotation(Table.class);
        String tableName = table.name();

        List<Field> fields = ReflectUtil.getAllFields(type);

        List<String> sqls = new ArrayList<String>();
        for (Field field : fields) {
            if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {
                continue;
            }

            GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class);
            if (null != generatedValue) {
                String sql = this.primary(field);
                sqls.add(sql);
                continue;
            }

            Column column = field.getAnnotation(Column.class);
            if (null != column) {
                String sql = this.columnName(field) + " " + this.columnType(field);
                sqls.add(sql);
                continue;
            }

            throw new RuntimeException("#131 field=" + field);
        }

        return "CREATE TABLE " + tableName + "(" + StringUtil.join(sqls) + ")";
    }

    public String primary(Field field) {
        return this.columnName(field) + " " + this.columnType(field) + " PRIMARY KEY AUTO_INCREMENT ";
    }

    public String columnName(Field field) {
        String _columnName = this._columnName(field);
        if (null != _columnName && !_columnName.startsWith("`") && !_columnName.endsWith("`")) {
            return "`" + _columnName + "`";
        }

        return _columnName;
    }

    private String _columnName(Field field) {
        Column column = field.getAnnotation(Column.class);
        if (null != column) {
            if (null != column.name() && !column.name().trim().isEmpty()) {
                return column.name();
            }

            return field.getName();
        }

        if (null != field.getAnnotation(Id.class)) {
            return field.getName();
        }

        throw new RuntimeException("#66 field=" + field);
    }

    protected String columnType(Field field) {
        Class<?> type = field.getType();
        if (Integer.class.equals(type)) {
            return "INTEGER"; // INTEGER // int(11)
        }

        if (String.class.equals(type)) {
            return "varchar(255)";
        }

        if (Timestamp.class.equals(type)) {
            return "timestamp";
        }

        if (Double.class.equals(type)) {
            return "double";
        }

        throw new RuntimeException("#133 field=" + field + ", type=" + type);
    }
}